/**
 * 模板渲染与数据回填的核心 Hook
 *
 * 目标：
 * - 统一模板配置（含字段与默认 HTML 内容）
 * - 支持字段校验、占位符回填、印章替换
 * - 支持“其他模板”的高自定义：自动解析占位符并合并为字段
 * - 提供基础安全能力（轻量清洗、可选转义），适配导出/预览
 */
import { ref, computed, watch } from 'vue'
import { ElMessage } from 'element-plus'

// 模版字段接口
/**
 * 单个字段配置
 * - key/label：占位符键与显示名称
 * - placeholder/defaultValue：输入提示与默认值
 * - required/validation：必填与自定义校验
 */
export interface TemplateField {
  key: string
  label: string
  placeholder?: string
  defaultValue?: string
  required?: boolean
  validation?: (value: string) => boolean | string
}

// 模版配置接口
/**
 * 模板配置
 * - type：模板类型名（与下拉一致）
 * - content：模板 HTML（包含形如 [姓名] 的占位符）
 * - fields：推荐/常用字段列表（“其他模板”会在此基础上自动扩展）
 */
export interface TemplateConfig {
  type: string
  content: string
  fields: TemplateField[]
}

// 模版数据接口
/**
 * 模板数据（可用于存储/还原）
 * - fields：当前字段值快照
 * - sealData：印章元数据（图片优先，其次文字印章）
 */
export interface TemplateData {
  type: string
  content: string
  fields: Record<string, string>
  sealData?: {
    id: string
    name: string
    image?: string
  }
}

// 可选项：用于控制渲染及安全
/**
 * 运行期选项
 * - escapeFieldValues：替换字段值时进行 HTML 转义，避免 XSS
 * - autoDetectFields：从模板 HTML 自动解析 [占位符] 并并入字段列表
 * - sanitizeHtml：对模板 HTML 做轻量安全清洗（移除 script/on* 事件/javascript:）
 * - additionalPlaceholders：非字段类占位符（如 [DOC_NO]、[CREATOR] 等）
 */
export interface TemplateOptions {
  escapeFieldValues?: boolean // 替换字段值时是否进行HTML转义
  autoDetectFields?: boolean // 是否自动从内容中解析占位符作为字段
  sanitizeHtml?: boolean // 是否对模板HTML进行基本安全过滤
  additionalPlaceholders?: Record<string, string> // 额外占位符（非字段类）
}

// 统一的模板配置中心
/**
 * 统一的模板配置中心
 * 说明：
 * - 所有模板的占位符统一使用 [占位符名] 形式，例如：[姓名]、[日期]；印章位为保留占位符 [SEAL_PLACEHOLDER]
 * - 可按需扩展新的模板类型，仅需在此处新增配置
 */
export const templateConfigs: Record<string, TemplateConfig> = {
  '在职证明': {
    type: '在职证明',
    content: `<div style="max-width: 800px; margin: 0 auto; padding: 40px;">
  <h1 style="text-align: center; font-size: 24px; font-weight: bold; margin: 0 0 40px 0; color: var(--el-text-color-primary, #333);">在职证明</h1>
  
  <div style="font-size: 16px; line-height: 2; color: var(--el-text-color-primary, #333);">
    <p style="text-indent: 2em; margin: 15px 0;">兹有<u>[员工姓名]</u>（身份证号码：<u>[身份证号]</u>），</p>
    <p style="text-indent: 2em; margin: 15px 0;">自<u>[入职日期]</u>在我公司工作至今，现任<u>[职位]</u>职务，</p>
    <p style="text-indent: 2em; margin: 15px 0;">每月薪资为<u>[薪资]</u>元。</p>
    <p style="text-indent: 2em; margin: 15px 0;">特此证明。</p>
  </div>
  
  <div style="margin-top: 80px;float: right;">
    <div style="flex: 1;">
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">公司名称：<u>[公司名称]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">日期：<u>[日期]</u></p>
    </div>
    <div style="flex: 1; text-align: center; position: relative;">
      <div style="position: absolute; top: -100px; left: 50%; transform: translateX(-50%); z-index: 10;">
        [SEAL_PLACEHOLDER]
      </div>
    </div>
  </div>
</div>`,
    fields: [
      { key: '员工姓名', label: '员工姓名', placeholder: '请输入员工姓名', required: true },
      { key: '身份证号', label: '身份证号', placeholder: '请输入身份证号', required: true },
      { key: '入职日期', label: '入职日期', placeholder: '请输入入职日期', required: true },
      { key: '职位', label: '职位', placeholder: '请输入职位', required: true },
      { key: '薪资', label: '薪资', placeholder: '请输入薪资', required: true },
      { key: '公司名称', label: '公司名称', placeholder: '请输入公司名称', required: true },
      { key: '日期', label: '日期', placeholder: '请输入日期', required: true }
    ]
  },
  '离职证明': {
    type: '离职证明',
    content: `<div style="max-width: 800px; margin: 0 auto; padding: 40px;">
  <h1 style="text-align: center; font-size: 24px; font-weight: bold; margin: 0 0 40px 0; color: var(--el-text-color-primary, #333);">离职证明</h1>
  
  <div style="font-size: 16px; line-height: 2; color: var(--el-text-color-primary, #333);">
    <p style="text-indent: 2em; margin: 15px 0;">兹证明<u>[员工姓名]</u>（身份证号码：<u>[身份证号]</u>），在公司</p>
    <p style="text-indent: 2em; margin: 15px 0;">担任<u>[职位]</u>职位，于<u>[离职年份]</u>年<u>[离职月份]</u>月<u>[离职日期]</u>日与其解除劳动关系，现已办</p>
    <p style="text-indent: 2em; margin: 15px 0;">理完离职手续，双方不存在任何劳动纠纷。</p>
    <p style="text-indent: 2em; margin: 15px 0;">特此证明。</p>
  </div>
  
  <div style="margin-top: 80px; float:right;">
    <div>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">公司盖章：</p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);"><u>[公司名称]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);"><u>[年份]</u>年<u>[月份]</u>月<u>[日期]</u>日</p>
    </div>
    <div style="text-align: center; position: relative;">
      <div style="position: absolute; top: -100px; left: 50%; transform: translateX(-50%); z-index: 10;">
        [SEAL_PLACEHOLDER]
      </div>
    </div>
  </div>
</div>`,
    fields: [
      { key: '员工姓名', label: '员工姓名', placeholder: '请输入员工姓名', required: true },
      { key: '身份证号', label: '身份证号', placeholder: '请输入身份证号', required: true },
      { key: '职位', label: '职位', placeholder: '请输入职位', required: true },
      { key: '离职年份', label: '离职年份', placeholder: '请输入离职年份', required: true },
      { key: '离职月份', label: '离职月份', placeholder: '请输入离职月份', required: true },
      { key: '离职日期', label: '离职日期', placeholder: '请输入离职日期', required: true },
      { key: '公司名称', label: '公司名称', placeholder: '请输入公司名称', required: true },
      { key: '年份', label: '年份', placeholder: '请输入年份', required: true },
      { key: '月份', label: '月份', placeholder: '请输入月份', required: true },
      { key: '日期', label: '日期', placeholder: '请输入日期', required: true }
    ]
  },
  '销售合同': {
    type: '销售合同',
    content: `<div style="max-width: 800px; margin: 0 auto; padding: 40px;">
  <h1 style="text-align: center; font-size: 24px; font-weight: bold; margin: 0 0 40px 0; color: var(--el-text-color-primary, #333);">销售合同</h1>
  
  <div style="font-size: 16px; line-height: 2; color: var(--el-text-color-primary, #333);">
    <div style="margin-bottom: 20px;">
      <p style="margin: 10px 0;"><strong>甲方（卖方）：</strong><u>[甲方名称]</u></p>
      <p style="margin: 10px 0;"><strong>乙方（买方）：</strong><u>[乙方名称]</u></p>
    </div>
    
    <p style="text-indent: 2em; margin: 15px 0;">经双方友好协商，就以下商品销售事宜达成如下协议：</p>
    
    <div style="margin: 20px 0; padding: 20px; border: 1px solid var(--el-border-color, #ddd); border-radius: 4px;">
      <p style="margin: 8px 0;"><strong>一、商品名称：</strong><u>[商品名称]</u></p>
      <p style="margin: 8px 0;"><strong>二、数量：</strong><u>[数量]</u></p>
      <p style="margin: 8px 0;"><strong>三、单价：</strong><u>[单价]</u></p>
      <p style="margin: 8px 0;"><strong>四、总金额：</strong><u>[总金额]</u></p>
    </div>
  </div>
  
  <div style="margin-top: 80px; display: flex; justify-content: space-between; align-items: flex-end;">
    <div style="flex: 1; text-align: center; position: relative;">
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">甲方（盖章）：<u>[甲方名称]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">日期：<u>[日期]</u></p>
      <div style="position: absolute; top: -40px; left: 50%; transform: translateX(-50%); z-index: 10;">
        [SEAL_PLACEHOLDER]
      </div>
    </div>
    <div style="flex: 1; text-align: center;">
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">乙方（盖章）：<u>[乙方名称]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">日期：<u>[日期]</u></p>
    </div>
  </div>
</div>`,
    fields: [
      { key: '甲方名称', label: '甲方名称', placeholder: '请输入甲方名称', required: true },
      { key: '乙方名称', label: '乙方名称', placeholder: '请输入乙方名称', required: true },
      { key: '商品名称', label: '商品名称', placeholder: '请输入商品名称', required: true },
      { key: '数量', label: '数量', placeholder: '请输入数量', required: true },
      { key: '单价', label: '单价', placeholder: '请输入单价', required: true },
      { key: '总金额', label: '总金额', placeholder: '请输入总金额', required: true },
      { key: '日期', label: '日期', placeholder: '请输入日期', required: true }
    ]
  },
  '劳动合同': {
    type: '劳动合同',
    content: `<div style="max-width: 800px; margin: 0 auto; padding: 40px;">
  <h1 style="text-align: center; font-size: 24px; font-weight: bold; margin: 0 0 40px 0; color: var(--el-text-color-primary, #333);">劳动合同</h1>
  
  <div style="font-size: 16px; line-height: 2; color: var(--el-text-color-primary, #333);">
    <div style="margin-bottom: 20px;">
      <p style="margin: 10px 0;"><strong>甲方（用人单位）：</strong><u>[公司名称]</u></p>
      <p style="margin: 10px 0;"><strong>乙方（劳动者）：</strong><u>[员工姓名]</u></p>
    </div>
    
    <p style="text-indent: 2em; margin: 15px 0;">根据《中华人民共和国劳动法》及相关法律法规，甲乙双方在平等自愿、协商一致的基础上，订立本劳动合同。</p>
    
    <div style="margin: 20px 0; padding: 20px; border: 1px solid var(--el-border-color, #ddd); border-radius: 4px;">
      <p style="margin: 8px 0;"><strong>一、合同期限：</strong><u>[合同期限]</u></p>
      <p style="margin: 8px 0;"><strong>二、工作内容：</strong><u>[工作内容]</u></p>
      <p style="margin: 8px 0;"><strong>三、工作地点：</strong><u>[工作地点]</u></p>
      <p style="margin: 8px 0;"><strong>四、劳动报酬：</strong><u>[劳动报酬]</u></p>
    </div>
  </div>
  
  <div style="margin-top: 80px; display: flex; justify-content: space-between; align-items: flex-end;">
    <div style="flex: 1; text-align: center; position: relative;">
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">甲方（盖章）：<u>[公司名称]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">日期：<u>[日期]</u></p>
      <div style="position: absolute; top: -40px; left: 50%; transform: translateX(-50%); z-index: 10;">
        [SEAL_PLACEHOLDER]
      </div>
    </div>
    <div style="flex: 1; text-align: center;">
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">乙方（签字）：<u>[员工姓名]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">日期：<u>[日期]</u></p>
    </div>
  </div>
</div>`,
    fields: [
      { key: '公司名称', label: '公司名称', placeholder: '请输入公司名称', required: true },
      { key: '员工姓名', label: '员工姓名', placeholder: '请输入员工姓名', required: true },
      { key: '合同期限', label: '合同期限', placeholder: '请输入合同期限', required: true },
      { key: '工作内容', label: '工作内容', placeholder: '请输入工作内容', required: true },
      { key: '工作地点', label: '工作地点', placeholder: '请输入工作地点', required: true },
      { key: '劳动报酬', label: '劳动报酬', placeholder: '请输入劳动报酬', required: true },
      { key: '日期', label: '日期', placeholder: '请输入日期', required: true }
    ]
  },
  '实习证明': {
    type: '实习证明',
    content: `<div style="max-width: 800px; margin: 0 auto; padding: 40px;">
  <h1 style="text-align: center; font-size: 24px; font-weight: bold; margin: 0 0 40px 0; color: var(--el-text-color-primary, #333);">实习证明</h1>
  
  <div style="font-size: 16px; line-height: 2; color: var(--el-text-color-primary, #333);">
    <p style="text-indent: 2em; margin: 15px 0;">兹有<u>[学生姓名]</u>（身份证号码：<u>[身份证号]</u>），</p>
    <p style="text-indent: 2em; margin: 15px 0;">系<u>[学校名称]</u><u>[专业名称]</u>专业学生，</p>
    <p style="text-indent: 2em; margin: 15px 0;">于<u>[实习开始日期]</u>至<u>[实习结束日期]</u>在我公司实习，</p>
    <p style="text-indent: 2em; margin: 15px 0;">实习岗位为<u>[实习岗位]</u>，实习期间表现良好。</p>
    <p style="text-indent: 2em; margin: 15px 0;">特此证明。</p>
  </div>
  
  <div style="margin-top: 80px;float:right;">
    <div>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">公司名称：<u>[公司名称]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">日期：<u>[日期]</u></p>
    </div>
    <div style="text-align: center; position: relative;">
      <div style="position: absolute; top: -100px; left: 50%; transform: translateX(-50%); z-index: 10;">
        [SEAL_PLACEHOLDER]
      </div>
    </div>
  </div>
</div>`,
    fields: [
      { key: '学生姓名', label: '学生姓名', placeholder: '请输入学生姓名', required: true },
      { key: '身份证号', label: '身份证号', placeholder: '请输入身份证号', required: true },
      { key: '学校名称', label: '学校名称', placeholder: '请输入学校名称', required: true },
      { key: '专业名称', label: '专业名称', placeholder: '请输入专业名称', required: true },
      { key: '实习开始日期', label: '实习开始日期', placeholder: '请输入实习开始日期', required: true },
      { key: '实习结束日期', label: '实习结束日期', placeholder: '请输入实习结束日期', required: true },
      { key: '实习岗位', label: '实习岗位', placeholder: '请输入实习岗位', required: true },
      { key: '公司名称', label: '公司名称', placeholder: '请输入公司名称', required: true },
      { key: '日期', label: '日期', placeholder: '请输入日期', required: true }
    ]
  },
  '采购合同': {
    type: '采购合同',
    content: `<div style="max-width: 800px; margin: 0 auto; padding: 40px;">
  <h1 style="text-align: center; font-size: 24px; font-weight: bold; margin: 0 0 40px 0; color: var(--el-text-color-primary, #333);">采购合同</h1>
  
  <div style="font-size: 16px; line-height: 2; color: var(--el-text-color-primary, #333);">
    <div style="margin-bottom: 20px;">
      <p style="margin: 10px 0;"><strong>甲方（买方）：</strong><u>[甲方名称]</u></p>
      <p style="margin: 10px 0;"><strong>乙方（卖方）：</strong><u>[乙方名称]</u></p>
    </div>
    
    <p style="text-indent: 2em; margin: 15px 0;">经双方友好协商，就以下商品采购事宜达成如下协议：</p>
    
    <div style="margin: 20px 0; padding: 20px; border: 1px solid var(--el-border-color, #ddd); border-radius: 4px;">
      <p style="margin: 8px 0;"><strong>一、商品名称：</strong><u>[商品名称]</u></p>
      <p style="margin: 8px 0;"><strong>二、数量：</strong><u>[数量]</u></p>
      <p style="margin: 8px 0;"><strong>三、单价：</strong><u>[单价]</u></p>
      <p style="margin: 8px 0;"><strong>四、总金额：</strong><u>[总金额]</u></p>
      <p style="margin: 8px 0;"><strong>五、交货时间：</strong><u>[交货时间]</u></p>
    </div>
  </div>
  
  <div style="margin-top: 80px; display: flex; justify-content: space-between; align-items: flex-end;">
    <div style="flex: 1; text-align: center; position: relative;">
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">甲方（盖章）：<u>[甲方名称]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">日期：<u>[日期]</u></p>
      <div style="position: absolute; top: -40px; left: 50%; transform: translateX(-50%); z-index: 10;">
        [SEAL_PLACEHOLDER]
      </div>
    </div>
    <div style="flex: 1; text-align: center;">
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">乙方（盖章）：<u>[乙方名称]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">日期：<u>[日期]</u></p>
    </div>
  </div>
</div>`,
    fields: [
      { key: '甲方名称', label: '甲方名称', placeholder: '请输入甲方名称', required: true },
      { key: '乙方名称', label: '乙方名称', placeholder: '请输入乙方名称', required: true },
      { key: '商品名称', label: '商品名称', placeholder: '请输入商品名称', required: true },
      { key: '数量', label: '数量', placeholder: '请输入数量', required: true },
      { key: '单价', label: '单价', placeholder: '请输入单价', required: true },
      { key: '总金额', label: '总金额', placeholder: '请输入总金额', required: true },
      { key: '交货时间', label: '交货时间', placeholder: '请输入交货时间', required: true },
      { key: '日期', label: '日期', placeholder: '请输入日期', required: true }
    ]
  },
  '保密协议': {
    type: '保密协议',
    content: `<div style="max-width: 800px; margin: 0 auto; padding: 40px;">
  <h1 style="text-align: center; font-size: 24px; font-weight: bold; margin: 0 0 40px 0; color: var(--el-text-color-primary, #333);">保密协议</h1>
  
  <div style="font-size: 16px; line-height: 2; color: var(--el-text-color-primary, #333);">
    <div style="margin-bottom: 20px;">
      <p style="margin: 10px 0;"><strong>甲方（公司）：</strong><u>[公司名称]</u></p>
      <p style="margin: 10px 0;"><strong>乙方（员工）：</strong><u>[员工姓名]</u></p>
    </div>
    
    <p style="text-indent: 2em; margin: 15px 0;">根据《中华人民共和国反不正当竞争法》等相关法律法规，甲乙双方就保密事宜达成如下协议：</p>
    
    <div style="margin: 20px 0; padding: 20px; border: 1px solid var(--el-border-color, #ddd); border-radius: 4px;">
      <p style="margin: 8px 0;"><strong>一、保密内容：</strong><u>[保密内容]</u></p>
      <p style="margin: 8px 0;"><strong>二、保密期限：</strong><u>[保密期限]</u></p>
      <p style="margin: 8px 0;"><strong>三、违约责任：</strong><u>[违约责任]</u></p>
    </div>
  </div>
  
  <div style="margin-top: 80px; display: flex; justify-content: space-between; align-items: flex-end;">
    <div style="flex: 1; text-align: center; position: relative;">
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">甲方（盖章）：<u>[公司名称]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">日期：<u>[日期]</u></p>
      <div style="position: absolute; top: -40px; left: 50%; transform: translateX(-50%); z-index: 10;">
        [SEAL_PLACEHOLDER]
      </div>
    </div>
    <div style="flex: 1; text-align: center;">
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">乙方（签字）：<u>[员工姓名]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">日期：<u>[日期]</u></p>
    </div>
  </div>
</div>`,
    fields: [
      { key: '公司名称', label: '公司名称', placeholder: '请输入公司名称', required: true },
      { key: '员工姓名', label: '员工姓名', placeholder: '请输入员工姓名', required: true },
      { key: '保密内容', label: '保密内容', placeholder: '请输入保密内容', required: true },
      { key: '保密期限', label: '保密期限', placeholder: '请输入保密期限', required: true },
      { key: '违约责任', label: '违约责任', placeholder: '请输入违约责任', required: true },
      { key: '日期', label: '日期', placeholder: '请输入日期', required: true }
    ]
  },
  '其他模板': {
    type: '其他模板',
    content: `<div style="max-width: 800px; margin: 0 auto; padding: 40px;">
  <h1 style="text-align: center; font-size: 24px; font-weight: bold; margin: 0 0 40px 0; color: var(--el-text-color-primary, #333);">[文档标题]</h1>
  
  <div style="font-size: 16px; line-height: 2; color: var(--el-text-color-primary, #333);">
    <p style="text-indent: 2em; margin: 15px 0;">[文档内容]</p>
  </div>
  
  <div style="margin-top: 80px; display: flex; justify-content: space-between; align-items: flex-end;">
    <div style="flex: 1; text-align: center; position: relative;">
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">[签署单位/人员]：<u>[单位/人员名称]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">[其他信息]</p>
      <div style="position: absolute; top: 0px; left: 50%; transform: translateX(-50%); z-index: 10;">
        [SEAL_PLACEHOLDER]
      </div>
    </div>
    <div style="flex: 1; text-align: center;">
    </div>
  </div>
</div>`,
    fields: [
      { key: '文档标题', label: '文档标题', placeholder: '请输入文档标题', required: true },
      { key: '文档内容', label: '文档内容', placeholder: '请输入文档内容', required: true },
      { key: '签署单位/人员', label: '签署单位/人员', placeholder: '请输入签署单位/人员', required: true },
      { key: '单位/人员名称', label: '单位/人员名称', placeholder: '请输入单位/人员名称', required: true },
      { key: '其他信息', label: '其他信息', placeholder: '请输入其他信息', required: false }
    ]
  },
  '入职通知': {
    type: '入职通知',
    content: `<div style="max-width: 800px; margin: 0 auto; padding: 40px;">
  <h1 style="text-align: center; font-size: 24px; font-weight: bold; margin: 0 0 40px 0; color: var(--el-text-color-primary, #333);">入职通知</h1>
  
  <div style="font-size: 16px; line-height: 2; color: var(--el-text-color-primary, #333);">
    <p style="text-indent: 2em; margin: 15px 0;">尊敬的<u>[员工姓名]</u>：</p>
    <p style="text-indent: 2em; margin: 15px 0;">恭喜您通过我公司的面试和考核，现正式通知您入职。</p>
    
    <div style="margin: 20px 0; padding: 20px; border: 1px solid var(--el-border-color, #ddd); border-radius: 4px;">
      <p style="margin: 8px 0;"><strong>入职信息：</strong></p>
      <p style="margin: 8px 0;"><strong>入职日期：</strong><u>[入职日期]</u></p>
      <p style="margin: 8px 0;"><strong>工作岗位：</strong><u>[工作岗位]</u></p>
      <p style="margin: 8px 0;"><strong>工作地点：</strong><u>[工作地点]</u></p>
      <p style="margin: 8px 0;"><strong>薪资待遇：</strong><u>[薪资待遇]</u></p>
    </div>
    
    <p style="text-indent: 2em; margin: 15px 0;">请携带相关证件按时报到，如有疑问请及时联系。</p>
  </div>
  
  <div style="margin-top: 80px;float:right;">
    <div>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">公司名称：<u>[公司名称]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">日期：<u>[日期]</u></p>
    </div>
    <div style="text-align: center; position: relative;">
      <div style="position: absolute; top: -100px; left: 50%; transform: translateX(-50%); z-index: 10;">
        [SEAL_PLACEHOLDER]
      </div>
    </div>
  </div>
</div>`,
    fields: [
      { key: '员工姓名', label: '员工姓名', placeholder: '请输入员工姓名', required: true },
      { key: '入职日期', label: '入职日期', placeholder: '请输入入职日期', required: true },
      { key: '工作岗位', label: '工作岗位', placeholder: '请输入工作岗位', required: true },
      { key: '工作地点', label: '工作地点', placeholder: '请输入工作地点', required: true },
      { key: '薪资待遇', label: '薪资待遇', placeholder: '请输入薪资待遇', required: true },
      { key: '公司名称', label: '公司名称', placeholder: '请输入公司名称', required: true },
      { key: '日期', label: '日期', placeholder: '请输入日期', required: true }
    ]
  },
  '转正通知': {
    type: '转正通知',
    content: `<div style="max-width: 800px; margin: 0 auto; padding: 40px;">
  <h1 style="text-align: center; font-size: 24px; font-weight: bold; margin: 0 0 40px 0; color: var(--el-text-color-primary, #333);">转正通知</h1>
  
  <div style="font-size: 16px; line-height: 2; color: var(--el-text-color-primary, #333);">
    <p style="text-indent: 2em; margin: 15px 0;">尊敬的<u>[员工姓名]</u>：</p>
    <p style="text-indent: 2em; margin: 15px 0;">经过试用期的考核，您的工作表现得到了公司的一致认可，现正式通知您转正。</p>
    
    <div style="margin: 20px 0; padding: 20px; border: 1px solid var(--el-border-color, #ddd); border-radius: 4px;">
      <p style="margin: 8px 0;"><strong>转正信息：</strong></p>
      <p style="margin: 8px 0;"><strong>转正日期：</strong><u>[转正日期]</u></p>
      <p style="margin: 8px 0;"><strong>工作岗位：</strong><u>[工作岗位]</u></p>
      <p style="margin: 8px 0;"><strong>薪资调整：</strong><u>[薪资调整]</u></p>
    </div>
    
    <p style="text-indent: 2em; margin: 15px 0;">恭喜您成为公司的正式员工，希望您继续努力，为公司发展贡献力量。</p>
  </div>
  
  <div style="margin-top: 80px;float:right;">
    <div>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">公司名称：<u>[公司名称]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">日期：<u>[日期]</u></p>
    </div>
    <div style="text-align: center; position: relative;">
      <div style="position: absolute; top: -100px; left: 50%; transform: translateX(-50%); z-index: 10;">
        [SEAL_PLACEHOLDER]
      </div>
    </div>
  </div>
</div>`,
    fields: [
      { key: '员工姓名', label: '员工姓名', placeholder: '请输入员工姓名', required: true },
      { key: '转正日期', label: '转正日期', placeholder: '请输入转正日期', required: true },
      { key: '工作岗位', label: '工作岗位', placeholder: '请输入工作岗位', required: true },
      { key: '薪资调整', label: '薪资调整', placeholder: '请输入薪资调整', required: true },
      { key: '公司名称', label: '公司名称', placeholder: '请输入公司名称', required: true },
      { key: '日期', label: '日期', placeholder: '请输入日期', required: true }
    ]
  },
  '调薪通知': {
    type: '调薪通知',
    content: `<div style="max-width: 800px; margin: 0 auto; padding: 40px;">
  <h1 style="text-align: center; font-size: 24px; font-weight: bold; margin: 0 0 40px 0; color: var(--el-text-color-primary, #333);">调薪通知</h1>
  
  <div style="font-size: 16px; line-height: 2; color: var(--el-text-color-primary, #333);">
    <p style="text-indent: 2em; margin: 15px 0;">尊敬的<u>[员工姓名]</u>：</p>
    <p style="text-indent: 2em; margin: 15px 0;">根据您的工作表现和公司政策，现对您的薪资进行调整。</p>
    
    <div style="margin: 20px 0; padding: 20px; border: 1px solid var(--el-border-color, #ddd); border-radius: 4px;">
      <p style="margin: 8px 0;"><strong>调薪信息：</strong></p>
      <p style="margin: 8px 0;"><strong>调薪日期：</strong><u>[调薪日期]</u></p>
      <p style="margin: 8px 0;"><strong>原薪资：</strong><u>[原薪资]</u></p>
      <p style="margin: 8px 0;"><strong>新薪资：</strong><u>[新薪资]</u></p>
      <p style="margin: 8px 0;"><strong>调薪幅度：</strong><u>[调薪幅度]</u></p>
    </div>
    
    <p style="text-indent: 2em; margin: 15px 0;">希望您继续努力，为公司发展做出更大贡献。</p>
  </div>
  
  <div style="margin-top: 80px;float:right;">
    <div>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">公司名称：<u>[公司名称]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">日期：<u>[日期]</u></p>
    </div>
    <div style="text-align: center; position: relative;">
      <div style="position: absolute; top: -100px; left: 50%; transform: translateX(-50%); z-index: 10;">
        [SEAL_PLACEHOLDER]
      </div>
    </div>
  </div>
</div>`,
    fields: [
      { key: '员工姓名', label: '员工姓名', placeholder: '请输入员工姓名', required: true },
      { key: '调薪日期', label: '调薪日期', placeholder: '请输入调薪日期', required: true },
      { key: '原薪资', label: '原薪资', placeholder: '请输入原薪资', required: true },
      { key: '新薪资', label: '新薪资', placeholder: '请输入新薪资', required: true },
      { key: '调薪幅度', label: '调薪幅度', placeholder: '请输入调薪幅度', required: true },
      { key: '公司名称', label: '公司名称', placeholder: '请输入公司名称', required: true },
      { key: '日期', label: '日期', placeholder: '请输入日期', required: true }
    ]
  },
  '请假条': {
    type: '请假条',
    content: `<div style="max-width: 800px; margin: 0 auto; padding: 40px;">
  <h1 style="text-align: center; font-size: 24px; font-weight: bold; margin: 0 0 40px 0; color: var(--el-text-color-primary, #333);">请假条</h1>
  
  <div style="font-size: 16px; line-height: 2; color: var(--el-text-color-primary, #333);">
    <p style="text-indent: 2em; margin: 15px 0;">本人<u>[员工姓名]</u>，因<u>[请假原因]</u>，特申请请假。</p>
    
    <div style="margin: 20px 0; padding: 20px; border: 1px solid var(--el-border-color, #ddd); border-radius: 4px;">
      <p style="margin: 8px 0;"><strong>请假信息：</strong></p>
      <p style="margin: 8px 0;"><strong>请假类型：</strong><u>[请假类型]</u></p>
      <p style="margin: 8px 0;"><strong>请假时间：</strong><u>[请假开始时间]</u> 至 <u>[请假结束时间]</u></p>
      <p style="margin: 8px 0;"><strong>请假天数：</strong><u>[请假天数]</u>天</p>
      <p style="margin: 8px 0;"><strong>联系电话：</strong><u>[联系电话]</u></p>
    </div>
    
    <p style="text-indent: 2em; margin: 15px 0;">请假期间，本人会妥善安排工作交接，确保不影响部门正常运转。</p>
  </div>
  
  <div style="margin-top: 80px; display: flex; justify-content: space-between; align-items: flex-end;">
    <div style="flex: 1;">
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">申请人：<u>[员工姓名]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">申请日期：<u>[申请日期]</u></p>
    </div>
    <div style="flex: 1; text-align: center; position: relative;">
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">审批人：<u>[审批人]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">审批日期：<u>[审批日期]</u></p>
      <div style="position: absolute; top: -20px; left: 50%; transform: translateX(-50%); z-index: 10;">
        [SEAL_PLACEHOLDER]
      </div>
    </div>
  </div>
</div>`,
    fields: [
      { key: '员工姓名', label: '员工姓名', placeholder: '请输入员工姓名', required: true },
      { key: '请假原因', label: '请假原因', placeholder: '请输入请假原因', required: true },
      { key: '请假类型', label: '请假类型', placeholder: '请输入请假类型', required: true },
      { key: '请假开始时间', label: '请假开始时间', placeholder: '请输入请假开始时间', required: true },
      { key: '请假结束时间', label: '请假结束时间', placeholder: '请输入请假结束时间', required: true },
      { key: '请假天数', label: '请假天数', placeholder: '请输入请假天数', required: true },
      { key: '联系电话', label: '联系电话', placeholder: '请输入联系电话', required: true },
      { key: '申请日期', label: '申请日期', placeholder: '请输入申请日期', required: true },
      { key: '审批人', label: '审批人', placeholder: '请输入审批人', required: true },
      { key: '审批日期', label: '审批日期', placeholder: '请输入审批日期', required: true }
    ]
  },
  '报销单': {
    type: '报销单',
    content: `<div style="max-width: 800px; margin: 0 auto; padding: 40px;">
  <h1 style="text-align: center; font-size: 24px; font-weight: bold; margin: 0 0 40px 0; color: var(--el-text-color-primary, #333);">报销单</h1>
  
  <div style="font-size: 16px; line-height: 2; color: var(--el-text-color-primary, #333);">
    <p style="text-indent: 2em; margin: 15px 0;">申请人<u>[员工姓名]</u>，现申请报销相关费用。</p>
    
    <div style="margin: 20px 0; padding: 20px; border: 1px solid var(--el-border-color, #ddd); border-radius: 4px;">
      <p style="margin: 8px 0;"><strong>报销信息：</strong></p>
      <p style="margin: 8px 0;"><strong>报销类型：</strong><u>[报销类型]</u></p>
      <p style="margin: 8px 0;"><strong>报销金额：</strong><u>[报销金额]</u>元</p>
      <p style="margin: 8px 0;"><strong>报销事由：</strong><u>[报销事由]</u></p>
      <p style="margin: 8px 0;"><strong>发生时间：</strong><u>[发生时间]</u></p>
      <p style="margin: 8px 0;"><strong>附件数量：</strong><u>[附件数量]</u>份</p>
    </div>
    
    <p style="text-indent: 2em; margin: 15px 0;">以上费用均为公务支出，请予以审批。</p>
  </div>
  
  <div style="margin-top: 80px; display: flex; justify-content: space-between; align-items: flex-end;">
    <div style="flex: 1;">
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">申请人：<u>[员工姓名]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">申请日期：<u>[申请日期]</u></p>
    </div>
    <div style="flex: 1; text-align: center; position: relative;">
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">审批人：<u>[审批人]</u></p>
      <p style="font-size: 16px; margin: 8px 0; color: var(--el-text-color-primary, #333);">审批日期：<u>[审批日期]</u></p>
      <div style="position: absolute; top: -20px; left: 50%; transform: translateX(-50%); z-index: 10;">
        [SEAL_PLACEHOLDER]
      </div>
    </div>
  </div>
</div>`,
    fields: [
      { key: '员工姓名', label: '员工姓名', placeholder: '请输入员工姓名', required: true },
      { key: '报销类型', label: '报销类型', placeholder: '请输入报销类型', required: true },
      { key: '报销金额', label: '报销金额', placeholder: '请输入报销金额', required: true },
      { key: '报销事由', label: '报销事由', placeholder: '请输入报销事由', required: true },
      { key: '发生时间', label: '发生时间', placeholder: '请输入发生时间', required: true },
      { key: '附件数量', label: '附件数量', placeholder: '请输入附件数量', required: true },
      { key: '申请日期', label: '申请日期', placeholder: '请输入申请日期', required: true },
      { key: '审批人', label: '审批人', placeholder: '请输入审批人', required: true },
      { key: '审批日期', label: '审批日期', placeholder: '请输入审批日期', required: true }
    ]
  }
}

// 使用模版的hooks
/**
 * useTemplate：模板选择、字段回填、印章替换与导出逻辑
 */
export function useTemplate() {
  // 响应式数据
  const selectedTemplateType = ref('')
  const templateContent = ref('')
  const fieldValues = ref<Record<string, string>>({})
  const sealData = ref<{ id: string; name: string; image?: string } | null>(null)
  const isPreviewMode = ref(false)
  /** 运行期可调选项（高自定义模板建议开启 autoDetectFields） */
  const options = ref<TemplateOptions>({
    escapeFieldValues: true,
    autoDetectFields: false,
    sanitizeHtml: true,
    additionalPlaceholders: {},
  })

  /**
   * 轻量 HTML 清洗：
   * - 移除 <script> 标签
   * - 移除内联事件处理（on*）
   * - 过滤 javascript: 协议
   * 注：非严格安全库，仅作为基础兜底；如需更严谨可替换为 DOMPurify 等专业库
   */
  const sanitizeHtml = (html: string): string => {
    if (!options.value.sanitizeHtml) return html
    let safe = html || ''
    // 移除脚本标签
    safe = safe.replace(/<script[\s\S]*?>[\s\S]*?<\/script>/gi, '')
    // 移除事件处理属性 on*
    safe = safe.replace(/ on[a-zA-Z]+\s*=\s*"[\s\S]*?"/g, '')
    safe = safe.replace(/ on[a-zA-Z]+\s*=\s*'[^']*?'/g, '')
    safe = safe.replace(/ on[a-zA-Z]+\s*=\s*[^\s>]+/g, '')
    // 处理 javascript: 协议
    safe = safe.replace(/href\s*=\s*"javascript:[^"]*"/gi, 'href="#"')
    safe = safe.replace(/href\s*=\s*'javascript:[^']*'/gi, "href='#'")
    return safe
  }

  /** 对字段值进行 HTML 转义，避免注入到 v-html 时造成 XSS */
  const escapeHtml = (input: string) =>
    input
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/\"/g, '&quot;')
      .replace(/'/g, '&#39;')

  // 模版类型列表
  const templateTypes = computed(() => {
    return Object.keys(templateConfigs).map(key => ({
      value: key,
      label: key
    }))
  })

  /** 当前模板配置（来自 templateConfigs） */
  const currentTemplateConfig = computed(() => {
    return templateConfigs[selectedTemplateType.value] || null
  })

  /**
   * 从 HTML 中解析占位符键名（形如 [键]），排除 [SEAL_PLACEHOLDER]
   */
  const extractPlaceholders = (html: string): string[] => {
    const keys = new Set<string>()
    if (!html) return []
    const regex = /\[([^\[\]]+)\]/g
    let match: RegExpExecArray | null
    while ((match = regex.exec(html)) !== null) {
      const key = match[1].trim()
      if (!key || key === 'SEAL_PLACEHOLDER') continue
      keys.add(key)
    }
    return Array.from(keys)
  }

  /**
   * 当前模板字段：显式配置字段 ∪ 自动解析字段
   * 仅在开启 autoDetectFields 或模板类型为“其他模板”时启用自动解析
   */
  const currentTemplateFields = computed(() => {
    const baseFields = currentTemplateConfig.value?.fields || []
    const needAuto = options.value.autoDetectFields || selectedTemplateType.value === '其他模板'
    if (!needAuto) return baseFields
    const detected = extractPlaceholders(templateContent.value)
    const detectedFields: TemplateField[] = detected.map((k) => ({ key: k, label: k, required: false }))
    const seen = new Set(baseFields.map((f) => f.key))
    const merged = baseFields.slice()
    detectedFields.forEach((f) => {
      if (!seen.has(f.key)) merged.push(f)
    })
    return merged
  })

  // 渲染后的模版内容
  /**
   * 渲染后的 HTML 内容
   * 顺序：
   * 1) 轻量清洗模板 HTML
   * 2) 替换字段（可选转义）
   * 3) 替换额外占位符（非字段）
   * 4) 替换印章占位符（无印章则移除）
   */
  const renderedContent = computed(() => {
    let content = sanitizeHtml(templateContent.value)

    // 替换字段占位符
    Object.keys(fieldValues.value).forEach(key => {
      let value = fieldValues.value[key] || `[${key}]`
      if (options.value.escapeFieldValues && value) {
        value = escapeHtml(value)
      }
      const regex = new RegExp(`\\[${key}\\]`, 'g')
      content = content.replace(regex, value)
    })

    // 替换额外占位符
    if (options.value.additionalPlaceholders) {
      Object.keys(options.value.additionalPlaceholders).forEach((k) => {
        const v = options.value.additionalPlaceholders![k]
        const regex = new RegExp(`\\[${k}\\]`, 'g')
        content = content.replace(regex, v)
      })
    }

    // 替换印章占位符
    if (sealData.value) {
      const sealHtml = generateSealHtml(sealData.value)
      content = content.replace(/\[SEAL_PLACEHOLDER\]/g, sealHtml)
    } else {
      // 如果没有印章数据，移除印章占位符
      content = content.replace(/\[SEAL_PLACEHOLDER\]/g, '')
    }

    return content
  })

  /**
   * 生成印章 HTML：有图片优先显示图片，否则显示文字印章
   */
  const generateSealHtml = (seal: { id: string; name: string; image?: string }) => {
    if (seal.image) {
      return `<img src="${seal.image}" alt="印章" style="width: 100px; height: 100px; max-width: 100px; max-height: 100px; display: inline-block; vertical-align: middle; object-fit: contain; position: relative; z-index: 10; opacity: 0.8;" />`
    } else {
      return `<div style="
        width: 100px; 
        height: 100px; 
        border: 2px solid #d32f2f; 
        border-radius: 50%; 
        display: inline-flex; 
        align-items: center; 
        justify-content: center; 
        text-align: center; 
        font-size: 10px; 
        font-weight: bold; 
        color: #d32f2f; 
        line-height: 1.2;
        background: rgba(211, 47, 47, 0.05);
        vertical-align: middle;
        box-sizing: border-box;
        position: relative;
        z-index: 10;
        opacity: 0.8;
      ">${seal.name}</div>`
    }
  }

  /**
   * 选择模板类型：
   * - 注入默认 HTML 与字段默认值
   * - 对于“其他模板”或开启 autoDetectFields，自动解析并补齐新占位符键
   */
  const selectTemplateType = (type: string) => {
    selectedTemplateType.value = type
    const config = templateConfigs[type]
    if (config) {
      templateContent.value = config.content
      // 初始化字段值
      fieldValues.value = {}
      config.fields.forEach(field => {
        fieldValues.value[field.key] = field.defaultValue || ''
      })
      // 对于高自定义模板，自动解析新增占位符并初始化
      if (options.value.autoDetectFields || type === '其他模板') {
        extractPlaceholders(templateContent.value).forEach((k) => {
          if (!(k in fieldValues.value)) fieldValues.value[k] = ''
        })
      }
    }
  }

  // 更新字段值
  const updateFieldValue = (key: string, value: string) => {
    fieldValues.value[key] = value
  }

  /** 设置印章数据 */
  const setSealData = (seal: { id: string; name: string; image?: string } | null) => {
    sealData.value = seal
  }

  /** 批量合并字段值（不会清空已有值） */
  const setFieldValues = (values: Record<string, string>) => {
    fieldValues.value = { ...fieldValues.value, ...values }
  }

  /** 合并设置运行期选项 */
  const setOptions = (partial: TemplateOptions) => {
    options.value = { ...options.value, ...partial }
  }

  /**
   * 设置自定义模板 HTML 内容：
   * - 适用于“其他模板”场景，支持任意结构的 HTML
   * - 会在开启 autoDetectFields 或类型为“其他模板”时自动解析并补齐字段键
   */
  const setCustomTemplateContent = (content: string) => {
    templateContent.value = content || ''
    if (options.value.autoDetectFields || selectedTemplateType.value === '其他模板') {
      const detected = extractPlaceholders(templateContent.value)
      detected.forEach((k) => {
        if (!(k in fieldValues.value)) fieldValues.value[k] = ''
      })
    }
  }

  /** 字段校验：必填项与自定义校验函数（返回错误数组） */
  const validateFields = () => {
    const errors: string[] = []

    currentTemplateFields.value.forEach(field => {
      if (field.required && (!fieldValues.value[field.key] || fieldValues.value[field.key].trim() === '')) {
        errors.push(`${field.label}为必填项`)
      }

      if (field.validation && fieldValues.value[field.key]) {
        const validationResult = field.validation(fieldValues.value[field.key])
        if (validationResult !== true) {
          errors.push(typeof validationResult === 'string' ? validationResult : `${field.label}格式不正确`)
        }
      }
    })

    return errors
  }

  /** 预览模板：校验通过后进入预览态 */
  const previewTemplate = () => {
    const errors = validateFields()
    if (errors.length > 0) {
      ElMessage.error(errors.join('\n'))
      return false
    }

    isPreviewMode.value = true
    return true
  }

  /**
   * 导出模板：默认导出HTML片段（上层可对接 PDF 导出）
   * - 校验通过才允许导出
   */
  const exportTemplate = () => {
    const errors = validateFields()
    if (errors.length > 0) {
      ElMessage.error(errors.join('\n'))
      return false
    }

    // 创建下载链接
    const blob = new Blob([renderedContent.value], { type: 'text/html' })
    const url = URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    link.download = `${selectedTemplateType.value}_${new Date().getTime()}.html`
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    URL.revokeObjectURL(url)

    ElMessage.success('模版导出成功')
    return true
  }

  /** 重置模板：清空字段与印章，恢复预览态与默认字段值 */
  const resetTemplate = () => {
    fieldValues.value = {}
    sealData.value = null
    isPreviewMode.value = false

    // 重新初始化字段值
    if (currentTemplateConfig.value) {
      currentTemplateConfig.value.fields.forEach(field => {
        fieldValues.value[field.key] = field.defaultValue || ''
      })
    }
  }

  /** 获取模板数据（用于存储或回填） */
  const getTemplateData = (): TemplateData => {
    return {
      type: selectedTemplateType.value,
      content: templateContent.value,
      fields: { ...fieldValues.value },
      sealData: sealData.value || undefined
    }
  }

  /** 设置模板数据（用于还原页面状态） */
  const setTemplateData = (data: TemplateData) => {
    selectedTemplateType.value = data.type
    templateContent.value = data.content
    fieldValues.value = { ...data.fields }
    sealData.value = data.sealData || null
  }

  // 监听模版类型变化
  watch(selectedTemplateType, (newType) => {
    if (newType && templateConfigs[newType]) {
      selectTemplateType(newType)
    }
  })

  return {
    // 响应式数据
    selectedTemplateType,
    templateContent,
    fieldValues,
    sealData,
    isPreviewMode,
    options,

    // 计算属性
    templateTypes,
    currentTemplateConfig,
    currentTemplateFields,
    renderedContent,

    // 方法
    selectTemplateType,
    updateFieldValue,
    setSealData,
    setFieldValues,
    setOptions,
    setCustomTemplateContent,
    extractPlaceholders,
    validateFields,
    previewTemplate,
    exportTemplate,
    resetTemplate,
    getTemplateData,
    setTemplateData
  }
}
